;Atari 1030 8050 internal ROM disassembly [CRC32 329B1D5B]
;
;Matched to 64Kbit external ROM [CRC32 7ABDB8E7]
;
;8048 clock speed: 4.032MHz
;	8.4KHz timer tick
;
;T0		TMS99532 RCVD (received data)
;T1		SIO Data Out (uninverted)
;INT	SIO Command (interrupt asserted when command activated)
;P1.0	(O) TMS99532 ALB (analog loopback enable)
;P1.1	(I) SIO Ready (1 = computer on)
;P1.2	(O) TMS99532 /ATE (answer tone enable)
;P1.3	(O) SIO Data In (uninverted)
;P1.4	(O) SIO Proceed (uninverted)
;P1.5	(O) SIO Interrupt (uninverted)
;P1.6	(I) TMS99532 /CD (carrier detect)
;P1.7	(O) On/off hook relay (0 = on hook)
;P2.0	(O) ROM A8
;P2.1	(O) ROM A9
;P2.2	(O) ROM A10
;P2.3	(O) ROM A11
;P2.4	(O) ROM A12
;P2.5	(O) TMS99532 SQT (squelch transmitter)
;P2.6	(O) TMS99532 O/A (originating / answering)
;P2.7	(O) TMS99532 TXD (transmit data)
;
;Internal RAM:
;00-07H	Register bank 0
;	R2	Wait counter (seconds)
;	R3	TINT A save
;	R4	Output shift counter (counts up to 40)
;	R5	Input shift phase counter (counts from 4)
;	R6	Flags (reset to 20H)
;		D0=1: Input shifting
;		D1=1: Input start bit valid
;		D2=1: Input checking for stop bit
;		D5=1: Output byte pending
;		D6=1: Output shifter active
;		D7=1: Command byte ready
;	R7	Shift index
;08-17H	Stack
;18-1FH	Register bank 1
;	R4	Output shift counter (counts up to 40)
;	R5	Input shift phase counter (counts from 4)
;	R6	Flags (reset to 25H)
;		D0=1: Input shifting
;		D1=1: Input start bit valid
;		D2=1: Input checking for stop bit
;		D5=1: Output byte pending
;		D6=1: Output shifter active
;	R7	Shift index
;
;20H	SIO input shifter
;21H	SIO output shifter
;22H	SIO input register
;23H	SIO output register
;24H	Command byte
;25H	Modem input shifter
;26H	Modem output shifter
;27H	Modem input register
;28H	Modem output register
;29H	
;2BH	TCNT R0 save
;2CH	TCNT R1 save
;2DH	Remaining long wait time for carrier wait (stashed from R2)
;2EH	Counter low (increments 0-11)
;2FH	Counter high (increments at 100Hz)
;30H	P1 shadow (reset to 7EH)
;	D0=1	Analog loopback enabled
;   D2=0    Answer tone enabled (also required for analog audio input)
;   D3=1    SIO data in, sending '1' to computer
;   D4=0    SIO proceed low, pulsed for one tick to indicate command completion
;   D5=0    SIO interrupt high, pulsed for one tick to indicate carrier change
;   D7=1    Phone off hook
;31H	P2 shadow (reset to 0E0H)
;	D5=1    Squelch transmitter (also required for analog audio input)
;	D6=1	Originate mode
;   D7=1    Transmitting '1' to other modem
;32H	General flags (reset to 8BH)
;   D0=1    Disable modem serial output
;   D1=1    Disable SIO serial output
;   D2=?    ???
;   D3=1    Modem suspended
;   D4=1    Send break pending
;   D5=1    Stability delay completed
;   D6=1    Connecting
;   D7=0    Carrier was last detected
;
;   D2 is set but doesn't appear to be used.
;
;   D5 is used to control a number of delays, including an initial connection
;   delay, delay to confirm stable carrier, and delay to wait for a lost
;   carrier to return before dropping the connection.
;
;33H	General flags saved during suspend
;34H	Shift processing temp

;===============================================================================
; Reset
;
0000:   SEL     RB0
0001:   JMP     0100H

;===============================================================================
; Interrupt - not used as external interrupt is not enabled
;
0003:   RETR
0004:   NOP
0005:   NOP
0006:   NOP

;===============================================================================
; Timer interrupt
;
0007:   JTF     000AH       ;clear TF and process timer interrupt
0009:   RETR                ;return (spurious interrupt?)

;===============================================================================
; Timer interrupt handler
;
000A:   MOV     R3,A
000B:   MOV     A,#0F9H     ;4.032MHz / 15 / 32 / 7 = 1200 interrupts/sec
000D:   MOV     T,A         ;rearm timer
000E:   MOV     A,R0        ;save R0 to 2BH
000F:   MOV     R0,#2BH     ; "
0011:   MOV     @R0,A       ; "
0012:   INC     R0          ;save R1 to 2CH
0013:   MOV     A,R1        ; "
0014:   MOV     @R0,A       ; "
0015:   MOV     R1,#31H     ;select P2 shadow
0017:   MOV     A,@R1       ;get P2 shadow
0018:   OUTL    P2,A        ;update port 2 from 31H shadow
0019:   DEC     R1          ;select P1 shadow
001A:   MOV     A,@R1       ;get P1 shadow
001B:   OUTL    P1,A        ;update port 1 from 30H shadow
001C:   INC     R1          ;select P2 shadow
001D:   MOV     R0,#2EH     ;increment counter low
001F:   INC     @R0         ; "
0020:   MOV     A,#0CH      ;check if counter low = 12
0022:   XRL     A,@R0       ; "
0023:   JNZ     0028H       ;jump if not
0025:   MOV     @R0,A       ;reset counter low to 0
0026:   INC     R0          ;select counter high (100Hz)
0027:   INC     @R0         ;increment counter high
0028:   MOV     A,@R1       ;read P2 shadow
0029:   CLR     F0          ;F0 = 0 for received 0
002A:   CLR     F1
002B:   JNT0    002EH       ;jump if received data was 0
002D:   CPL     F0          ;F0 = 1 for received 1
002E:   CPL     A
002F:   JB7     0032H       ;jump if transmit data was low
0031:   CPL     F1
0032:   SEL     RB1
0033:   CALL    0071H       ;update modem receive shifter
0035:   SEL     RB0
0036:   MOV     R1,#32H     ;select general flags
0038:   MOV     A,@R1       ;read general flags
0039:   DEC     R1          ;select P2 shadow
003A:   JB0     0048H
003C:   MOV     A,@R1       ;read P2 shadow
003D:   JF1     0043H       ;jump if should transmit a '1' bit
003F:   ANL     A,#7FH      ;transmit data low
0041:   JMP     0045H       ;
0043:   ORL     A,#80H      ;transmit data high
0045:   MOV     @R1,A       ;write P2 shadow
0046:   DEC     R1          ;select P1 shadow
0047:   MOV     A,@R1       ;read P1 shadow
0048:   CLR     F0
0049:   CLR     F1
004A:   JNT1    004DH       ;jump if SIO data out low
004C:   CPL     F0          ;F0 = SIO data out state
004D:   CPL     A
004E:   JB3     0051H       ;jump if SIO data in low
0050:   CPL     F1          ;F1 = SIO data in state
0051:   CALL    0071H       ;update SIO receive shifter
0053:   MOV     R1,#32H     ;select general flags
0055:   MOV     A,@R1       ;read general flags
0056:   DEC     R1          ;select P2 shadow
0057:   DEC     R1          ;select P1 shadow
0058:   JB1     0064H       ;skip if SIO serial output disabled
005A:   MOV     A,@R1       ;read P1 shadow
005B:   JF1     0061H       ;jump if SIO data in was high
005D:   ANL     A,#0F7H     ;restore SIO data in low
005F:   JMP     0063H
0061:   ORL     A,#08H      ;restore SIO data in high
;
0063:   MOV     @R1,A       ;write P1 shadow
0064:   MOV     A,@R1       ;read P1 shadow
0065:   ORL     A,#30H      ;raise SIO proceed (idle) and interrupt (connected)
0067:   MOV     @R1,A       ;write P1 shadow
;
; pop registers and exit
;
0068:   MOV     R0,#2CH     ;restore R1
006A:   MOV     A,@R0       ; "
006B:   MOV     R1,A        ; "
006C:   DEC     R0          ;restore R0
006D:   MOV     A,@R0       ; "
006E:   MOV     R0,A        ; "
006F:   MOV     A,R3        ;restore A
0070:   RETR                ;exit interrupt

;===============================================================================
; Update shift registers
;
; (runs in either RB0 for SIO or RB1 for modem)
;
; Entry:
;   F0 = 1 if received bit was a 1
;
0071:   MOV     A,R7
0072:   MOV     R0,A
0073:   MOV     A,R6        ;get shift flags
0074:   JB0     0080H       ;jump if input shifter active
0076:   JF0     00B5H       ;jump if input high
0078:   MOV     A,R6        ;get shift flags
0079:   ORL     A,#01H      ;set input shifter active
007B:   ANL     A,#0FBH     ;clear checking for stop bit flag
007D:   MOV     R6,A        ;set shift flags
007E:   JMP     00B5H       ;input shifter done, go do output

0080:   JB1     0092H       ;process data/stop bit if start bit confirmed
0082:   JF0     008DH       ;reject if start bit is too short (<0.5 bit)
0084:   ORL     A,#02H      ;set start bit valid
0086:   MOV     R6,A        ;set shift flags
0087:   MOV     @R0,#80H    ;initialize shifter for new byte
0089:   MOV     R5,#04H     ;set input counter to 4 phases = 1 bit
008B:   JMP     00B5H       ;input shifter done, go do output

;
; handle false start bit
;
008D:   ANL     A,#0FEH     ;clear input shift active
008F:   MOV     R6,A        ;set shift flags
0090:   JMP     00B5H       ;input shifter done, go do output

;
; process data/stop bit
;
0092:   DJNZ    R5,00B5H    ;wait until sample time
0094:   MOV     R5,#04H     ;reset sample counter
0096:   CPL     F0          ;invert received bit
0097:   JB2     00ADH       ;jump if expecting stop bit
0099:   CLR     C           ;copy received bit to carry
009A:   JF0     009DH       ; "
009C:   CPL     C           ; "
009D:   MOV     A,@R0       ;shift in bit
009E:   RRC     A           ; "
009F:   MOV     @R0,A       ; "
00A0:   JNC     00B5H       ;jump if byte not finished
00A2:   INC     R0          ;R0=21H/26H
00A3:   INC     R0          ;R0=22H/27H
00A4:   MOV     @R0,A       ;save received byte
00A5:   DEC     R0          ;R0=21H/26H
00A6:   DEC     R0          ;R0=20H/25H
00A7:   MOV     A,R6        ;get shift flags
00A8:   ORL     A,#04H      ;set stop bit flag
00AA:   MOV     R6,A        ;set shift flags
00AB:   JMP     00B5H

;
; process stop bit
;
00AD:   JF0     00B2H       ;jump if received 1 as stop bit (framing error)
00AF:   CALL    036DH       ;process received byte
00B1:   MOV     A,R6        ;get shift flags
00B2:   ANL     A,#0FCH     ;clear stop bit flag
00B4:   MOV     R6,A        ;set shift flags

;
; process output shifter
;
00B5:   INC     R4          ;update output shift counter
00B6:   MOV     A,#03H      ;test phase
00B8:   ANL     A,R4        ; "
00B9:   JNZ     00EAH       ;jump if not time to shift output yet
00BB:   MOV     A,R6        ;get shifter flags
00BC:   CPL     A           ;invert
00BD:   JB6     00D7H       ;jump if output shifter idle
00BF:   MOV     A,#24H      ;test if output count = 40 (10 bits)
00C1:   XRL     A,R4        ; "
00C2:   JNZ     00CCH       ;jump if output shift not done yet
00C4:   CLR     F1          ;set F1 for stop bit
00C5:   CPL     F1          ; "
00C6:   MOV     A,R6        ;get shift flags
00C7:   ANL     A,#0BFH     ;clear output shifter active bit
00C9:   MOV     R6,A        ;set shift flags
00CA:   JMP     00EAH       ;all done

;
; shift next output bit
;
00CC:   INC     R0          ;select output shift register
00CD:   MOV     A,@R0       ;get current output byte
00CE:   RRC     A           ;shift next bit out
00CF:   MOV     @R0,A       ;update current output byte
00D0:   DEC     R0          ;select input shift register
00D1:   CLR     F1          ;copy output bit to F1 for caller
00D2:   JNC     00EAH       ; "
00D4:   CPL     F1          ; "
00D5:   JMP     00EAH       ;exit

;
; begin next output byte if one is pending
;
00D7:   JB5     00EAH       ;jump if no output byte pending
00D9:   INC     R0          ;R0 = 21H/26H
00DA:   INC     R0          ;R0 = 22H/27H
00DB:   INC     R0          ;R0 = 23H/28H
00DC:   MOV     A,@R0       ;read pending output byte
00DD:   DEC     R0          ;R0 = 22H/27H
00DE:   DEC     R0          ;R0 = 21H/26H
00DF:   MOV     @R0,A       ;write to output shifter
00E0:   DEC     R0          ;R0 = 20H/25H
00E1:   MOV     A,R6        ;get shifter flags
00E2:   ANL     A,#0DFH     ;reset output byte pending bit
00E4:   ORL     A,#40H      ;set output shifter active bit
00E6:   MOV     R6,A        ;set shifter flags
00E7:   MOV     R4,#00H     ;reset output shift counter
00E9:   CLR     F1          ;F1=0 so caller outputs start bit
00EA:   RET

;===============================================================================
00EB:   NOP
00EC:   NOP
00ED:   NOP
00EE:   NOP
00EF:   NOP
00F0:   NOP
00F1:   NOP
00F2:   NOP
00F3:   NOP
00F4:   NOP
00F5:   NOP
00F6:   NOP
00F7:   NOP
00F8:   NOP
00F9:   NOP
00FA:   NOP
00FB:   NOP
00FC:   NOP
00FD:   NOP
00FE:   NOP
00FF:   NOP

;===============================================================================
; Power-up reset
;
0100:   DIS     TCNTI       ;disable timer interrupt
0101:   CALL    0366H       ;initialize I/O ports
0103:   CALL    03A0H       ;initialize variables       
0105:   JMP     043AH       ;jump to SIO command loop

;===============================================================================
; Modem processing loop
;
0107:   MOV     A,#0F9H
0109:   MOV     T,A
010A:   MOV     R0,#2EH     ;select counter lot
010C:   MOV     @R0,#00H    ;clear counter low
010E:   INC     R0
010F:   MOV     @R0,#00H    ;2.56s
0111:   MOV     R2,#01H     ;+1s
0113:   STRT    T           ;start timer
0114:   EN      TCNTI       ;enable timer interrupt
0115:   MOV     A,R6        ;check command byte pending flag
0116:   CPL     A           ;invert it
0117:   JB7     011BH       ;jump if not command
0119:   CALL    0200H       ;handle command
011B:   CALL    012DH       ;do main loop processing
011D:   MOV     R1,#32H     ;select general flags
011F:   MOV     A,@R1       ;read general flags
0120:   JB3     0127H       ;exit if suspended
0122:   IN      A,P1        ;read port 1
0123:   JB1     0115H       ;keep waiting if SIO ready
0125:   JMP     0100H       ;computer off -- reinitialize

;
; Transition from modem processing loop to SIO command loop
;
0127:   ANL     P1,#0EFH    ;lower SIO proceed
0129:   ORL     P1,#10H     ;raise SIO proceed
012B:   JMP     043AH       ;return to SIO command loop

;===============================================================================
; Update modem state
;
; This runs continuously in modem mode while not processing command bytes.
;
012D:   MOV     R1,#32H     ;select general flags
012F:   IN      A,P1        ;read port 1
0130:   RL      A           ;shift /CD to bit 7
0131:   XRL     A,@R1       ;check for carrier detect change
0132:   JB7     0185H       ;jump if CD changed

;------------------------------------------------------------------------------
; Carrier detect not changed handling
;
0134:   MOV     A,@R1       ;read general flags
0135:   CPL     A           ;invert
0136:   JB5     0157H       ;jump if not waiting for carrier
;
; %--1-----: initial connection delay passed
;
0138:   JB7     0151H       ;jump if carrier detected (inverted)
;
; %1-1-----: initial connection delay passed, no carrier
;
013A:   MOV     A,R2        ;check long wait counter
013B:   JNZ     01F2H       ;jump if still running
;
; %1-1-----: timed out waiting for carrier -> hang up
;
013D:   MOV     A,@R1       ;read general flags
013E:   ORL     A,#03H      ;disable SIO and modem transmission
0140:   ANL     A,#9FH      ;clear connecting flags
0142:   MOV     @R1,A       ;write general flags
0143:   DEC     R1          ;select P2 shadow
0144:   DEC     R1          ;select P1 shadow
0145:   MOV     A,@R1       ;read P1 shadow
0146:   ANL     A,#6FH      ;on hook, lower SIO proceed
0148:   MOV     @R1,A       ;write P1 shadow
0149:   INC     R1          ;select P2 shadow
014A:   MOV     A,@R1       ;read P2 shadow
014B:   ORL     A,#20H      ;squelch transmitter
014D:   MOV     @R1,A       ;write P2 shadow
014E:   INC     R1          ;select general flags
014F:   JMP     01F2H

;
; %0-1-----: initial connection delay passed, carrier detected -> connected
;
0151:   ORL     A,#20H      ;clear initial connection delay passed flag (inv.)
0153:   CPL     A           ;uninvert
0154:   MOV     @R1,A       ;write general flags
0155:   JMP     01FDH       ;exit

;..............................................................................
;
; %--0-----: initial connection delay passed (connected or not)
;
0157:   JB6     017AH       ;jump if already connected (inverted)
;
; %-10-----: connecting, waiting for carrier
;
0159:   MOV     A,R2        ;check long wait counter
015A:   JNZ     01F2H       ;jump if still running
;
; %-10-----: connecting, carrier not detected
;
015C:   MOV     A,@R1       ;read general flags
015D:   ORL     A,#20H      ;set initial connection delay passed
015F:   MOV     @R1,A       ;write general flags
0160:   DEC     R1          ;select P2 shadow
0161:   MOV     A,@R1       ;read P2 shadow
0162:   JB6     0173H       ;jump if originating
;
; %-10-----: connecting while answering, carrier not detected
;
0164:   ANL     A,#0DFH     ;unsquelch
0166:   MOV     @R1,A       ;write P2 shadow
0167:   INC     R1          ;select general flags
0168:   MOV     R0,#2EH     ;select counter low
016A:   MOV     @R0,#00H    ;clear it
016C:   INC     R0          ;select counter high
016D:   MOV     @R0,#9CH    ;set to -100 (1s)
016F:   MOV     R2,#1EH     ;set carrier wait to 30 seconds
0171:   JMP     01FDH

;
; %-10-----: connecting while originating, carrier not detected
;
0173:   INC     R1          ;select general flags
0174:   MOV     R0,#2DH     ;get remaining carrier wait time
0176:   MOV     A,@R0       ; "
0177:   MOV     R2,A        ;set long wait counter to resume carrier wait
0178:   JMP     01FDH

;
; %-00-----: send break processing
;
017A:   JB4     01F2H       ;jump if break is not pending
017C:   MOV     A,R2        ;get carrier wait counter
017D:   JNZ     01F2H       ;jump if still waiting
017F:   DEC     R1          ;select P2 shadow
0180:   CALL    0297H       ;finish break
0182:   INC     R1          ;select general flags
0183:   JMP     01F2H       ;update timeout and exit

;------------------------------------------------------------------------------
; Carrier detect changed handling
;
; Entry:
;   R1 = 32H (general flags)
;
0185:   MOV     A,@R1       ;read general flags
0186:   JB7     01BBH       ;jump if -CD previously (carrier detected now)

;..............................................................................
;
; carrier lost
;
0188:   JB5     0198H       ;jump if waiting for carrier
;
; %0-0-----: carrier lost when already connected
;
018A:   ORL     A,#20H      ;set flag waiting for carrier to come back
018C:   MOV     @R1,A
018D:   MOV     R0,#2EH     ;select counter low
018F:   MOV     @R0,#00H    ;clear
0191:   INC     R0          ;select counter high
0192:   MOV     @R0,#9CH    ;set to -100 (1s)
0194:   MOV     R2,#01H     ;1 second long wait
0196:   JMP     01FDH

; 
; %0-1-----: carrier lost and waiting for carrier to come back
;
0198:   MOV     A,R2        ;check long wait counter
0199:   JNZ     01F2H       ;ignore if still counting
;
; %0-1-----: carrier lost timer expired -- hang up
;
019B:   MOV     A,@R1       ;read general flags
019C:   ORL     A,#03H      ;disable SIO and modem transmission
019E:   MOV     @R1,A       ;write general flags
019F:   DEC     R1          ;select P2 shadow
01A0:   MOV     A,@R1       ;read P2 shadow
01A1:   ORL     A,#20H      ;squelch transmitter
01A3:   MOV     @R1,A       ;write P2 shadow
01A4:   DEC     R1          ;select P1 shadow
01A5:   MOV     A,@R1       ;read P1 shadow
01A6:   ANL     A,#7FH      ;on hook
01A8:   MOV     @R1,A       ;write P1 shadow
01A9:   INC     R1          ;select P2 shadow
01AA:   INC     R1          ;select general flags
01AB:   MOV     A,@R1       ;read general flags
01AC:   JB3     01F2H       ;jump if modem suspended
01AE:   ORL     A,#80H      ;mark carrier as no longer detected
01B0:   ANL     A,#0DFH     ;clear waiting for carrier flag
01B2:   MOV     @R1,A       ;write general flags
01B3:   MOV     R0,#30H     ;select P1 shadow
01B5:   MOV     A,@R0       ;read P1 shadow
01B6:   ANL     A,#0DFH     ;lower SIO interrupt (not connected)
01B8:   MOV     @R0,A       ;write P1 shadow
01B9:   JMP     01F2H       ;

;------------------------------------------------------------------------------
;
; %1-------: carrier newly detected
;
01BB:   CPL     A           ;invert general flags
01BC:   JB5     01D2H       ;jump if initial delay not completed (inverted)
;
; %1-1-----: carrier detected, initial delay passed
;
01BE:   ORL     A,#20H      ;clear initial delay flag
01C0:   JB6     01D2H       ;jump if not connecting (inverted)
;
; %110-----: connecting, carrier detected
;
01C2:   CPL     A           ;uninvert
01C3:   MOV     @R1,A       ;write general flags
01C4:   MOV     R0,#2DH     ;save off remaining long wait time
01C6:   MOV     A,R2        ; "
01C7:   MOV     @R0,A       ; "
01C8:   INC     R0          ;select counter low
01C9:   MOV     @R0,#00H    ;clear counter low
01CB:   INC     R0          ;select counter high
01CC:   MOV     @R0,#0D8H   ;set to -40 (0.4s)
01CE:   MOV     R2,#01H     ;carrier confirm time 0.4s
01D0:   JMP     01FDH       ;all done

;
; %1-0-----: carrier detected, initial delay not passed yet
;
01D2:   JB6     01DFH       ;jump if not connecting (inverted)
;
; %110-----: connected, carrier gained before initial delay passed
;
01D4:   CPL     A           ;uninvert general flags
01D5:   MOV     @R1,A       ;write general flags
01D6:   MOV     A,R2        ;get long wait timer
01D7:   JNZ     01F2H       ;jump if not expired yet
01D9:   MOV     A,@R1       ;read general flags
01DA:   ANL     A,#0BFH     ;clear connecting flag
01DC:   MOV     @R1,A       ;write general flags
01DD:   JMP     01FDH       ;all done

;
; %100-----: connected, carrier regained after being lost
;
01DF:   CPL     A           ;uninvert general flags
01E0:   MOV     @R1,A       ;write general flags
01E1:   JB3     01ECH       ;jump if modem suspended
01E3:   ANL     A,#5CH      ;clear initial delay, on-hook, and shift suspend flags
01E5:   MOV     @R1,A       ;write general flags
01E6:   MOV     R0,#30H     ;select P1 shadow
01E8:   MOV     A,@R0       ;read P1 shadow
01E9:   ANL     A,#0DFH     ;lower SIO interrupt (not connected)
01EB:   MOV     @R0,A       ;write P1 shadow
;
01EC:   DEC     R1          ;select P2 shadow
01ED:   MOV     A,@R1       ;read P2 shadow
01EE:   ANL     A,#0DFH     ;unsquelch transmitter
01F0:   MOV     @R1,A       ;write P2 shadow
01F1:   INC     R1          ;select general flags

;------------------------------------------------------------------------------
;
; update long wait counter
;
01F2:   MOV     A,R2
01F3:   JZ      01FDH
01F5:   MOV     R0,#2FH     ;select counter high
01F7:   MOV     A,@R0       ;read counter high
01F8:   JNZ     01FDH       ;jump if counter not expired
01FA:   MOV     @R0,#9CH    ;set counter to -100 (1s)
01FC:   DEC     R2
01FD:   RET

;===============================================================================
01FE:   NOP
01FF:   NOP

;===============================================================================
; Modem command handler (300 baud)
;
0200:   MOV     A,R6        ;get shift flags
0201:   ANL     A,#7FH      ;clear command byte pending bit
0203:   MOV     R6,A        ;set shift flags
0204:   MOV     R1,#32H     ;select general flags
0206:   MOV     R0,#24H     ;select command byte
0208:   MOV     A,@R1       ;read general flags
0209:   DEC     R1          ;select P2 shadow
020A:   JB3     0211H       ;jump if modem suspended
020C:   MOV     A,@R0       ;get received command byte
020D:   RLC     A           ;test if high bit set
020E:   JNC     021AH       ;jump to process only if high bit clear
;
; invalid command exit
;
0210:   RET

0211:   MOV     A,@R0       ;read command byte
0212:   XRL     A,#51H      ;check for Q (reset modem)
0214:   JZ      021AH
0216:   XRL     A,#08H      ;check for Y (resume modem)
0218:   JNZ     0210H       ;exit if not Q or Y while suspended
;
; dispatch command
;
021A:   MOV     A,@R0       ;read command byte
021B:   JMPP    @A          ;execute command handler

;===============================================================================
; Pull SIO proceed low for end of command
;
021C:   DEC     R1          ;select P1 shadow
021D:   MOV     A,@R1       ;read P1 shadow
021E:   ANL     A,#0EFH     ;lower SIO proceed for end of command (leading edge)
0220:   MOV     @R1,A       ;write P1 shadow
0221:   RET

;===============================================================================
; 'Y' command (resume modem)
;
0222:   INC     R1          ;select general flags
0223:   INC     R1          ;select suspended general flags
0224:   MOV     A,@R1       ;read suspended general flags
0225:   DEC     R1          ;select general flags
0226:   ORL     A,#04H
0228:   ANL     A,#0F7H     ;clear modem suspended flag
022A:   MOV     @R1,A       ;write general flags
022B:   DEC     R1          ;select P2 shadow
022C:   JMP     021CH       ;finish command (pull SIO proceed)

;===============================================================================
; 'Z' command (suspend modem)
;
022E:   INC     R1          ;select general flags
022F:   MOV     A,@R1       ;read general flags
0230:   JB5     0210H
0232:   INC     R1          ;select suspended general flags
0233:   MOV     @R1,A       ;save off general flags
0234:   CALL    023EH       ;wait for output shifters to finish
0236:   MOV     A,@R1       
0237:   DEC     R1
0238:   ORL     A,#0BH      ;disable shifters and set suspended flag
023A:   MOV     @R1,A
023B:   DEC     R1          ;select P2 shadow
023C:   JMP     021CH       ;finish command (pull SIO proceed)

;===============================================================================
; Wait for output shifters to finish
;
023E:   MOV     A,R6        ;read shift flags
023F:   JB6     023EH       ;wait for SIO output shifter to finish
0241:   MOV     R0,#1EH     ;select modem shift flags (RB1/R6)
0243:   MOV     A,@R0       ;read modem shift flags
0244:   JB6     0243H       ;wait for modem output shifter to finish
0246:   RET

;===============================================================================
0247:   NOP

;===============================================================================
; Command jump table
;
; When the modem is suspended, 
;
0248: 7B        ;48H H -> 027B  Send break signal
0249: 5B        ;49H I -> 025B  Set originate mode
024A: 61        ;4AH J -> 0261  Set answer mode
024B: FF        ;4BH K -> 02FF  Begin pulse dial
024C: C1        ;4CH L -> 02C1  Pick up phone
024D: A3        ;4DH M -> 02A3  Hang up phone
024E: 10        ;4EH N -> 0210  <invalid>
024F: F5        ;4FH O -> 02F5  Begin tone dial
0250: F7        ;50H P -> 02F7  Start 30 second timeout
0251: 71        ;51H Q -> 0271  Reset modem
0252: 10        ;52H R -> 0210  <invalid>
0253: 10        ;53H S -> 0210  <invalid>
0254: 10        ;54H T -> 0210  <invalid>
0255: 10        ;55H U -> 0210  <invalid>
0256: 10        ;56H V -> 0210  <invalid>
0257: 67        ;57H W -> 0267  Set analog loopback test
0258: 69        ;58H X -> 0269  Clear analog loopback test
0259: 22        ;59H Y -> 0222  Resume modem
025A: 2E        ;5AH Z -> 022E  Suspend modem

;===============================================================================
; 'I' command (set originate mode)
;
025B:   MOV     A,@R1       ;read P2 shadow
025C:   ORL     A,#40H      ;turn on origination mode
025E:   MOV     @R1,A       ;write P2 shadow
025F:   JMP     021CH       ;finish command (pull SIO proceed)

;===============================================================================
; 'J' command (set answer mode)
;
0261:   MOV     A,@R1       ;read P2 shadow
0262:   ANL     A,#9FH      ;select answering mode and unsquelch
0264:   MOV     @R1,A       ;write P2 shadow
0265:   JMP     021CH       ;finish command (pull SIO proceed)

;===============================================================================
; 'W' command trampoline (set analog loopback test)
;
0267:   JMP     03BDH

;===============================================================================
; 'X' command (clear analog loopback test)
;
0269:   DEC     R1          ;select P1 shadow
026A:   MOV     A,@R1       ;read P1 shadow
026B:   ANL     A,#0FEH     ;turn off analog loopback (ALB)
026D:   MOV     @R1,A       ;write P1 shadow
026E:   INC     R1          ;select P2 shadow
026F:   JMP     021CH       ;finish command (pull SIO proceed)

;===============================================================================
; 'Q' command (reset modem)
;
0271:   CALL    023EH       ;wait for output shifters to finish
0273:   DIS     TCNTI
0274:   CALL    0366H
0276:   CALL    03A0H
0278:   EN      TCNTI
0279:   JMP     02BBH

;===============================================================================
; 'H' command (send break signal)
;
027B:   INC     R1          ;select general flags
027C:   MOV     A,@R1       ;read general flags
027D:   JB7     02A0H
027F:   JB5     02A0H
0281:   CALL    023EH       ;wait for output shifters to finish
0283:   MOV     A,@R1       ;read general flags
0284:   ORL     A,#13H      ;set break flag, disable shifters
0286:   MOV     R0,#2EH     ;select counter low
0288:   MOV     @R0,#00H    ;reset
028A:   INC     R0          ;select counter high
028B:   MOV     @R0,#0CEH   ;set to -50 (0.5s)
028D:   MOV     R2,#01H     ;0.5s delay
028F:   MOV     @R1,A       ;write general flags
0290:   DEC     R1          ;select P2 shadow
0291:   MOV     A,@R1       ;read P2 shadow
0292:   ANL     A,#7FH      ;begin transmitting space
0294:   MOV     @R1,A       ;write P2 shadow
0295:   JMP     021CH       ;finish command (pull SIO proceed)

;===============================================================================
; Break completion handler
;
0297:   MOV     A,@R1       ;read P2 shadow
0298:   ORL     A,#80H      ;transmit data high
029A:   MOV     @R1,A       ;write P2 shadow
029B:   INC     R1          ;select general flags
029C:   MOV     A,@R1       ;read general flags
029D:   ANL     A,#0ECH     ;clear break, re-enable transmitters
029F:   MOV     @R1,A       ;write general flags
02A0:   DEC     R1          ;select P2 shadow
02A1:   JMP     021CH       ;finish command (pull SIO proceed)

;===============================================================================
; 'M' command (hang up phone)
;
02A3:   CALL    023EH       ;wait for output shifters to finish
02A5:   DIS     TCNTI       ;enter critical section
02A6:   MOV     A,@R1       ;read P2 shadow
02A7:   ORL     A,#0A0H     ;squelch and raise transmit data
02A9:   MOV     @R1,A       ;write P2 shadow
02AA:   DEC     R1          ;select P1 shadow
02AB:   MOV     A,@R1       ;read P1 shadow
02AC:   ORL     A,#08H      ;raise data in line
02AE:   ANL     A,#7FH      ;on hook
02B0:   MOV     @R1,A       ;write P1 shadow
02B1:   INC     R1          ;select P2 shadow
02B2:   INC     R1          ;select general flags
02B3:   MOV     @R1,#83H
02B5:   INC     R1
02B6:   MOV     @R1,#83H
02B8:   DEC     R1          ;select general flags
02B9:   DEC     R1          ;select P2 shadow
02BA:   EN      TCNTI       ;leave critical section
02BB:   IN      A,P1        ;read port 1
02BC:   CPL     A           ;invert
02BD:   JB6     02BBH       ;keep waiting while carrier detected
02BF:   JMP     021CH       ;finish command (pull SIO proceed)

;===============================================================================
; 'L' command (pick up phone)
;
02C1:   INC     R1          ;select general flags
02C2:   MOV     A,@R1       ;read general flags
02C3:   DEC     R1          ;select P2 shadow
02C4:   CPL     A           ;invert
02C5:   JB7     021CH       ;if carrier already detected, finish immediately (pull SIO proceed)
02C7:   MOV     R2,#1EH     ;set carrier wait time to 30 seconds
02C9:   MOV     A,#9CH      ;-100 (1s)
02CB:   CALL    02CFH       ;begin wait for carrier
02CD:   JMP     021CH       ;finish command (pull SIO proceed)

;===============================================================================
; Begin wait for carrier
;
; Entry:
;   A = -delay in 10ms increments
;
02CF:   MOV     R0,#2EH     ;select counter low
02D1:   MOV     @R0,#00H    ;clear it
02D3:   INC     R0          ;select counter high
02D4:   MOV     @R0,A       ;set counter high value
02D5:   DEC     R1          ;select P1 shadow
02D6:   MOV     A,@R1       ;read P1 shadow
02D7:   ORL     A,#80H      ;go off hook
02D9:   MOV     @R1,A       ;write P1 shadow
02DA:   INC     R1          ;select P2 shadow
02DB:   MOV     A,@R1       ;read P2 shadow
02DC:   ORL     A,#20H      ;squelch transmitter
02DE:   MOV     @R1,A       ;write P2 shadow
02DF:   INC     R1          ;select 32H
02E0:   CLR     C           ;C=0 if originating
02E1:   JB6     02E4H       ;jump if originating
02E3:   CPL     C           ;C=1 if answering
02E4:   MOV     A,@R1       ;read general flags
02E5:   JNC     02F0H       ;jump if originating
02E7:   ORL     A,#40H
02E9:   MOV     @R1,A       ;write general flags
02EA:   MOV     @R0,#38H    ;set wait timer to -56 (200 counts)
02EC:   MOV     R2,#01H     ;wait delay = 2 seconds
02EE:   JMP     02F3H

02F0:   ORL     A,#60H      ;enable 2s delay and then wait for carrier
02F2:   MOV     @R1,A       ;set general flags
02F3:   DEC     R1          ;select P2 shadow
02F4:   RET

;===============================================================================
; 'O' command trampoline (begin tone dial)
;
02F5:   JMP     0400H

;===============================================================================
; 'P' command (start 30 second timeout)
;
02F7:   JMP     0432H

;===============================================================================
02F9:   NOP
02FA:   NOP
02FB:   NOP
02FC:   NOP
02FD:   NOP
02FE:   NOP

;===============================================================================
; 'K' command (begin pulse dial)
;
02FF:   DEC     R1
0300:   MOV     A,@R1       ;read P1 shadow
0301:   INC     R1
0302:   JB7     030BH       ;jump if on hook
0304:   MOV     A,#38H
0306:   CALL    02CFH       ;begin wait for carrier
0308:   MOV     A,@R0       ;wait for 2s interdigit delay
0309:   JNZ     0308H       ; "
;
; pulse dialing loop
;
030B:   CALL    021CH       ;lower SIO proceed
030D:   DIS     TCNTI       ;disable timer interrupt
030E:   MOV     A,R6        ;read shift flags
030F:   ANL     A,#7CH      ;clear command byte ready and input shifting flags
0311:   MOV     R6,A        ;write shift flags
0312:   EN      TCNTI       ;enable timer interrupt
0313:   INC     R1
0314:   IN      A,P1        ;read port 1
0315:   JB1     0318H       ;jump if SIO ready
0317:   RET                 ;exit (computer off)

;
; wait for byte from computer
;
0318:   MOV     A,R6        ;get shift status
0319:   CPL     A           ;invert
031A:   JB7     0314H       ;keep waiting if no byte ready
031C:   ORL     A,#80H      ;set (clear) byte pending bit
031E:   CPL     A           ;uninvert
031F:   MOV     R6,A        ;set shift status
;
; check for reset command
;
0320:   MOV     R0,#24H     ;select received byte
0322:   MOV     A,@R0       ;read received byte
0323:   XRL     A,#51H      ;check if Q (reset modem)
0325:   JNZ     0329H       ;jump if not reset
0327:   JMP     0271H       ;invoke Q handler
;
; process received digit
;
0329:   MOV     A,@R0       ;read received byte
032A:   ANL     A,#0FH      ;mask to low 4 bits
032C:   JZ      030BH       ;ignore if 0
032E:   MOV     R2,A        ;save digit count
032F:   ANL     A,#0CH      ;check if 0C-0FH
0331:   XRL     A,#0CH      ; "
0333:   JZ      030BH       ;ignore if 0C-0FH
0335:   MOV     A,R2        ;restore digit count
0336:   XRL     A,#0BH      ;check if 0BH
0338:   JNZ     033CH       ;jump if regular digit
033A:   JMP     02C1H       ;0BH -> end dial and go off hook ("L" command)

033C:   MOV     A,#0C4H     ;set delay to -60
033E:   CALL    035CH       ;delay 0.6s
0340:   DEC     R1          ;select P1 shadow
0341:   MOV     A,@R1       ;read P1 shadow
0342:   ANL     A,#7FH      ;on hook
0344:   MOV     @R1,A       ;write P1 shadow
0345:   INC     R1          ;select P2 shadow
0346:   MOV     A,#0FAH     ;-6
0348:   CALL    035CH       ;delay 60ms
034A:   MOV     A,@R1       ;read P2 shadow
034B:   ORL     A,#20H      ;squelch transmitter
034D:   MOV     @R1,A       ;write P2 shadow
034E:   DEC     R1          ;select P1 shadow
034F:   MOV     A,@R1       ;read P1 shadow
0350:   ORL     A,#80H      ;off hook
0352:   MOV     @R1,A       ;write P1 shadow
0353:   INC     R1          ;select P2 shadow
0354:   MOV     A,#0FCH     ;-4
0356:   CALL    035CH       ;delay 40ms
0358:   DJNZ    R2,0340H    ;repeat until number of pulses completed
035A:   JMP     030BH       ;return to pulse dialing loop

;===============================================================================
; Delay 10ms*(256-A)
;
035C:   MOV     R0,#2EH
035E:   MOV     @R0,#00H
0360:   INC     R0
0361:   MOV     @R0,A
0362:   MOV     A,@R0
0363:   JNZ     0362H
0365:   RET

;===============================================================================
; Initialize I/O ports
;
0366:   MOV     A,#7EH
0368:   OUTL    P1,A
0369:   MOV     A,#0E0H
036B:   OUTL    P2,A
036C:   RET

;===============================================================================
; Process received byte (modem or SIO)
;
; Entry:
;   R0 = shift base (20H/25H)
;
036D:   INC     R0          ;R0 = 21H/26H
036E:   INC     R0          ;R0 = 22H/27H
036F:   MOV     A,PSW       ;check if RB1
0370:   ANL     A,#10H      ; "
0372:   JNZ     0381H       ;jump if RB1
0374:   JNI     0378H       ;jump if SIO command asserted
0376:   JMP     0381H       ;copy byte to other side

0378:   MOV     A,@R0       ;read last received byte
0379:   INC     R0          ;R0 = 23H/28H
037A:   INC     R0          ;R0 = 24H/29H
037B:   MOV     @R0,A       ;write to command byte
037C:   MOV     A,R6        ;get shift flags
037D:   ORL     A,#80H      ;set command pending flag
037F:   JMP     039CH       ;exit

;
; Copy byte from input shifter to opposite output shifter
;
0381:   MOV     R1,#34H     ;select shift temp
0383:   MOV     A,@R0       ;read last received byte
0384:   MOV     @R1,A       ;save in shift temp
0385:   MOV     A,PSW       ;toggle register bank
0386:   XRL     A,#10H      ; "
0388:   MOV     PSW,A       ; "
0389:   MOV     A,R7        ;A = 20H/25H
038A:   ADD     A,#03H      ;A = 23H/28H
038C:   MOV     R0,A        ;R0 = 23H/28H
038D:   MOV     R1,#34H     ;select shift temp
038F:   MOV     A,@R1       ;restore last received byte
0390:   MOV     @R0,A       ;write to output shifter
0391:   MOV     A,R6        ;get shift flags
0392:   ORL     A,#20H      ;set output byte pending
0394:   MOV     R6,A        ;set shift flags
0395:   MOV     A,PSW       ;toggle register bank
0396:   XRL     A,#10H      ; "
0398:   MOV     PSW,A       ; "
0399:   MOV     A,R6        ;get shift flags on source
039A:   ANL     A,#7FH      ;clear received byte ready on source
;
039C:   MOV     R6,A        ;set shift status
039D:   MOV     A,R7        ;restore shift address
039E:   MOV     R0,A        ; "
039F:   RET

;===============================================================================
; Initialize variables
;
03A0:   MOV     R0,#07H     ;set SIO R7 (shift offset) to 20H
03A2:   MOV     @R0,#20H    ; "
03A4:   DEC     R0          ;set SIO shift flags to 00H
03A5:   MOV     @R0,#00H    ; "
03A7:   MOV     R0,#1FH     ;set modem R7 (shift offset) to 25H
03A9:   MOV     @R0,#25H    ; "
03AB:   DEC     R0          ;set modem shift flags to 00H
03AC:   MOV     @R0,#00H    ; "
03AE:   MOV     R0,#32H     ;reset general flags
03B0:   MOV     @R0,#8BH    ; "
03B2:   INC     R0          ;
03B3:   MOV     @R0,#8BH
03B5:   MOV     R0,#30H     ;set P1 shadow to 7EH
03B7:   MOV     @R0,#7EH    ; "
03B9:   INC     R0          ;set P2 shadow to 0E0H
03BA:   MOV     @R0,#0E0H   ; "
03BC:   RET

;===============================================================================
; 'W' command (set analog loopback test)
;
03BD:   DEC     R1          ;select P1 shadow (30H)
03BE:   MOV     A,@R1       ;read P1 shadow
03BF:   ORL     A,#01H      ;turn on analog loopback (ALB)
03C1:   MOV     @R1,A       ;write P1 shadow
03C2:   INC     R1          ;select P2 shadow
03C3:   MOV     A,@R1       ;read P2 shadow
03C4:   ANL     A,#0DFH     ;unsquelch transmitter
03C6:   MOV     @R1,A       ;write P2 shadow
03C7:   JMP     021CH       ;end command (pull SIO proceed)

;===============================================================================
03C9:   NOP
03CA:   NOP
03CB:   NOP
03CC:   NOP
03CD:   NOP
03CE:   NOP
03CF:   NOP
03D0:   NOP
03D1:   NOP
03D2:   NOP
03D3:   NOP
03D4:   NOP
03D5:   NOP
03D6:   NOP
03D7:   NOP
03D8:   NOP
03D9:   NOP
03DA:   NOP
03DB:   NOP
03DC:   NOP
03DD:   NOP
03DE:   NOP
03DF:   NOP
03E0:   NOP
03E1:   NOP
03E2:   NOP
03E3:   NOP
03E4:   NOP
03E5:   NOP
03E6:   NOP
03E7:   NOP
03E8:   NOP
03E9:   NOP
03EA:   NOP
03EB:   NOP
03EC:   NOP
03ED:   NOP
03EE:   NOP
03EF:   NOP
03F0:   NOP
03F1:   NOP
03F2:   NOP
03F3:   NOP
03F4:   NOP
03F5:   NOP
03F6:   NOP
03F7:   NOP
03F8:   NOP
03F9:   NOP
03FA:   NOP
03FB:   NOP
03FC:   NOP
03FD:   NOP
03FE:   NOP
03FF:   NOP

;===============================================================================
; 'O' command (begin tone dial)
;
0400:   DEC     R1          ;select P1 shadow
0401:   MOV     A,@R1       ;read P1 shadow
0402:   INC     R1          ;select P2 shadow
0403:   JB7     040CH       ;jump if off hook
0405:   MOV     A,#38H      ;delay = 2s
0407:   CALL    02CFH       ;begin wait for carrier
0409:   MOV     A,@R0       ;wait for delay
040A:   JNZ     0409H       ; "
040C:   DEC     R1          ;select P1 shadow
040D:   MOV     A,@R1       ;read P1 shadow
040E:   ANL     A,#0FBH     ;assert /ATE
0410:   MOV     @R1,A       ;write P1 shadow
0411:   INC     R1          ;select P2 shadow
0412:   MOV     A,@R1       ;read P2 shadow
0413:   ORL     A,#20H      ;squelch transmitter (/ATE + SQT enables EXI)
0415:   MOV     @R1,A       ;write P2 shadow
0416:   CALL    021CH       ;lower SIO proceed
0418:   INC     R1          ;select general flags
0419:   IN      A,P1        ;read P1
;
; wait for command byte
;
041A:   JB1     041DH       ;jump if SIO ready
041C:   RET                 ;exit immediate if computer off
041D:   MOV     A,R6        ;get shift flags
041E:   CPL     A           ;invert
041F:   JB7     0419H       ;keep waiting if no command byte
;
0421:   ORL     A,#80H      ;clear command byte ready bit (inverted)
0423:   CPL     A           ;uninvert
0424:   MOV     R6,A        ;set shift flags
0425:   MOV     R0,#24H     ;select command byte
0427:   MOV     A,@R0       ;read command byte
0428:   XRL     A,#51H      ;check if Q (reset modem)
042A:   JNZ     042EH       ;skip if not
042C:   JMP     0271H       ;execute Q (reset modem) command and exit
042E:   XRL     A,#01H      ;check if P (start 30 second timeout)
0430:   JNZ     0419H       ;keep waiting if not
;
; 'P' command (start 30 second timeout)
;
0432:   DEC     R1          ;select P1 shadow
0433:   MOV     A,@R1       ;read P1 shadow
0434:   ORL     A,#04H      ;deassert /ATE to stop audio pass-through
0436:   MOV     @R1,A       ;write P1 shadow
0437:   INC     R1          ;select P2 shadow
0438:   JMP     02C1H       ;jump to L command (pick up phone) handler

;===============================================================================
; SIO command loop
;
043A:   DIS     TCNTI       ;disable timer counter
043B:   MOV     R3,#14H     ;set disk retry counter to 20
043D:   IN      A,P1        ;read port 1
043E:   JB1     0444H       ;jump if SIO ready
0440:   CALL    0366H       ;computer off - reset I/O port configuration
0442:   JMP     043DH       ;keep waiting for computer to turn on

0444:   JNI     0444H       ;wait for command line to be asserted
0446:   MOV     R2,#05H     ;receive command frame - 5 bytes
0448:   MOV     R0,#35H     ;...starting at address 035H
044A:   CALL    0505H       ;...do receive
044C:   JF0     04B4H       ;jump if byte received at 300 baud
044E:   MOV     A,R2        ;check if we completed the frame
044F:   JNZ     043DH       ;ignore and return to wait loop if so (framing error)
0451:   MOV     R0,#35H     ;calculate SIO checksum for buffer at 35H
0453:   MOV     R2,#04H     ;frame length = 4 bytes
0455:   CALL    0569H       ;compute checksum
0457:   XRL     A,@R0       ;compare against received checksum
0458:   JNZ     043DH       ;ignore frame on checksum fail
045A:   MOV     R0,#35H     ;set pointer to device ID byte
045C:   MOV     A,#31H      ;D1: device ID
045E:   XRL     A,@R0       ;check if request is for D1:
045F:   JZ      0483H       ;jump if so
0461:   MOV     A,#58H      ;1030 device ID
0463:   XRL     A,@R0       ;check if request is for us
0464:   JNZ     043BH       ;jump if not

;
; 1030 SIO command handler
;
0466:   INC     R0          ;advance to command byte
0467:   MOV     A,#3CH      ;check if handler download command
0469:   XRL     A,@R0       ; "
046A:   JNZ     0476H       ;jump if not
;
; T: handler download command ($3C)
;
046C:   CALL    04C8H       ;send ACK+Complete
046E:   CLR     F1
046F:   CALL    0597H       ;send T: handler
0471:   MOV     A,R5
0472:   CALL    04D9H       ;send SIO byte at 19200 baud
0474:   JMP     043BH       ;end command

0476:   MOV     A,#3BH      ;check if ModemLink download command
0478:   XRL     A,@R0       ; "
0479:   JZ      047FH       ;jump if so
;
; Unhandled command
;
047B:   CALL    0500H       ;send NAK
047D:   JMP     043BH       ;end command

;
; ModemLink download command ($3B)
;
047F:   CALL    0579H       ;send NAK
0481:   JMP     043BH       ;end command

;
; Fake disk drive command handler
;
0483:   INC     R0          ;advance to command byte
0484:   MOV     A,R3        ;check retry counter
0485:   JNZ     0499H       ;if non-zero, ignore Read Sector
0487:   MOV     A,#52H      ;check if command is Read Sector
0489:   XRL     A,@R0       ; "
048A:   JNZ     043BH       ;jump if not (ignore command)
;
; Read Sector ($52) handler
;
048C:   INC     R0          ;advance to AUX1 byte
048D:   MOV     A,@R0       ;read AUX1
048E:   DEC     A           ;check for sector 1
048F:   JNZ     043BH       ;jump if LSB not for sector 1
0491:   INC     R0          ;advance to AUX2
0492:   MOV     A,@R0       ;read AUX2
0493:   JNZ     043BH       ;jump if MSB not for sector 1
0495:   CALL    0600H       ;read fake boot sector
0497:   JMP     043BH       ;end command

0499:   MOV     A,#53H      ;check if command is Status
049B:   XRL     A,@R0       ; "
049C:   JNZ     043BH       ;jump if not
;
; Status command ($53) handler
;
049E:   DJNZ    R3,043DH    ;ignore command if not 20th attempt
04A0:   CALL    04C8H       ;send ACK+Complete
04A2:   MOV     R0,#0AFH    ;send from 04AFH
04A4:   MOV     R2,#05H     ;4 bytes + checksum
04A6:   MOV     A,R0
04A7:   INC     R0
04A8:   MOVP    A,@A        ;read next status byte
04A9:   CALL    04D9H       ;send SIO byte at 19200 baud
04AB:   DJNZ    R2,04A6H    ;repeat until 4 bytes + checksum sent
04AD:   JMP     043DH

;===============================================================================
; Fake disk drive status
;
04AF:   DB      000H,000H,0E0H,000H,0E0H

;===============================================================================
; Check 300 baud command byte for Q/Y to exit SIO command loop
;
04B4:   MOV     A,@R0       ;get received byte
04B5:   XRL     A,#51H      ;check if Q (reset modem)
04B7:   JZ      04BEH       ;jump if so
04B9:   MOV     A,@R0
04BA:   XRL     A,#59H      ;check if Y (resume modem)
04BC:   JNZ     043BH       ;ignore byte and resume SIO service loop if not
;
; exit SIO command loop
;
04BE:   MOV     A,@R0       ;get received byte
04BF:   MOV     R0,#24H     ;select command byte
04C1:   MOV     @R0,A       ;store command byte
04C2:   MOV     R6,#80H     ;set shift flags = 80H (command byte ready)
04C4:   MOV     R7,#20H     ;reset shift pointer
04C6:   JMP     0107H       ;jump to modem processing loop

;===============================================================================
; Send ACK and then Complete
;
04C8:   MOV     A,#41H      ;ACK
04CA:   CALL    04D9H       ;send SIO byte at 19200 baud
04CC:   MOV     R7,#07H     ;2
04CE:   CALL    0564H       ;8  delay
04D0:   DJNZ    R7,04CEH    ;2  longer delay
04D2:   MOV     A,#43H      ;Complete
04D4:   CALL    04D9H       ;send SIO byte at 19200 baud
04D6:   MOV     R5,#00H
04D8:   RET

;===============================================================================
; Send SIO byte at 19200 baud
;
; Entry:
;   A = byte to send
;   R5 = incoming checksum
;
; Exit:
;   R5 = updated checksum
;
; Timing:
;   14 machine cycles per bit (19200.0 baud)
;   145 machine cycles per byte including CALL
;
04D9:   MOV     R6,A        ;1   stash byte to send
04DA:   CLR     C           ;1   update checksum
04DB:   ADD     A,R5        ;1    "
04DC:   ADDC    A,#00H      ;2    "
04DE:   MOV     R5,A        ;1    "
04DF:   ANL     P1,#0F7H    ;2   lower SIO data in for start bit
04E1:   MOV     A,R6        ;1   restore byte to send
04E2:   MOV     R6,#08H     ;2   set counter for 8 data bits
04E4:   CALL    0567H       ;5   <-- delay
04E6:   RR      A           ;1
04E7:   JB7     04EDH       ;2   jump if sending a 1 bit
04E9:   ANL     P1,#0F7H    ;2   lower SIO data in
04EB:   JMP     04F1H       ;2

04ED:   ORL     P1,#08H     ;2   raise SIO data in
04EF:   JMP     04F1H       ;2
04F1:   DJNZ    R6,04E4H    ;2   --> loop for 8 bits (14*8 = 112 mcyc)
04F3:   CALL    0564H       ;8   delay
04F5:   ORL     P1,#08H     ;2   raise SIO data in for stop bit
04F7:   CALL    0564H       ;8   delay
04F9:   RET                 ;2

;===============================================================================
04FA:   NOP
04FB:   NOP
04FC:   NOP
04FD:   NOP
04FE:   NOP
04FF:   NOP

;===============================================================================
; Send SIO NAK
;
0500:   MOV     A,#4EH      ;NAK
0502:   CALL    04D9H       ;send SIO byte at 19200 baud
0504:   RET

;===============================================================================
; Receive SIO command frame
;
; Exit:
;   F0 = 0 if received at 19200 baud
;   F0 = 1 if received at 300 baud
;
0505:   CLR     F0
0506:   CPL     F0
0507:   JNI     050BH       ;jump if SIO command asserted
0509:   JMP     0505H       ;loop until SIO command

; wait for start bit
050B:   JNT1    0513H       ;jump if SIO data out low for start bit
050D:   JNI     050BH       ;keep waiting if SIO command still asserted
050F:   MOV     R3,#14H     ;
0511:   JMP     0534H

0513:   CALL    0567H       ;5  delay
0515:   JT1     050BH       ;2  jump back if SIO data out high, false start bit
0517:   MOV     R6,#08H     ;2  count 8 data bits
0519:   MOV     A,#00H      ;2
051B:   NOP                 ;1
051C:   JNI     0520H       ;2  begin if SIO command still asserted
051E:   JMP     0534H       ;   bail out, SIO command frame truncated

0520:   CALL    0567H       ;5  delay
0522:   JT1     0526H       ;2  jump if SIO data out high
0524:   JMP     0528H       ;2

0526:   ORL     A,#01H      ;2  mark '1' bit received
0528:   RR      A           ;2  shift
0529:   DJNZ    R6,051CH    ;2  loop until 8 data bits received
052B:   MOV     @R0,A       ;1  store received byte
052C:   INC     R0          ;1  next byte
052D:   CALL    0567H       ;5  delay
052F:   JNT1    0538H       ;2  jump if SIO data out low -> framing error
0531:   CLR     F0          ;1
0532:   DJNZ    R2,050BH    ;2  loop until whole frame received
0534:   JNI     0534H       ;2  wait for SIO command to deassert
0536:   CLR     F0          ;1  receive successful
0537:   RET

0538:   JNZ     0534H       ;fail if non-zero byte (call will ignore from R2 > 0)
053A:   JF0     053EH       ;try to reinterpret as 300 baud if first byte
053C:   JMP     0534H       ;fail the frame

053E:   MOV     R7,#16H
;
; alignment loop
;
0540:   JT1     0534H       ;2
0542:   JNI     0546H       ;2
0544:   JMP     0534H       ;2
0546:   CALL    0564H       ;8  delay
0548:   DJNZ    R7,0540H    ;2  loop for bit delay (308 mcyc total)
;
054A:   MOV     R6,#09H
;
; bit loop (896 mcyc/bit = 300.0 baud)
;
054C:   MOV     R7,#0B1H    ;2  reset bit delay
054E:   JNI     0552H       ;2  <--
0550:   JMP     0534H       ;2
0552:   NOP                 ;1
0553:   DJNZ    R7,054EH    ;2  --> loop for bit delay (885 mcyc total)
0555:   DJNZ    R6,055BH    ;2  loop until 9 bits received
0557:   JNT1    0534H       ;2  jump if SIO data out low (framing error)
0559:   MOV     @R0,A       ;1  store received byte
055A:   RET

055B:   JT1     055FH       ;2  jump if SIO data out high
055D:   JMP     0561H       ;2  shift in a 0

055F:   ORL     A,#01H      ;2  shift in a 1
0561:   RR      A           ;1  shift
0562:   JMP     054CH       ;2  next bit

;===============================================================================
; Delay line
;
0564:   NOP                 ;call here for 8 mcyc delay
0565:   NOP
0566:   NOP
0567:   NOP                 ;call here for 5 mcyc delay
0568:   RET

;===============================================================================
; Calculate SIO frame checksum
;
0569:   CLR     C
056A:   MOV     A,#00H
056C:   ADDC    A,@R0
056D:   INC     R0
056E:   DJNZ    R2,056CH
0570:   ADDC    A,#00H
0572:   RET

;===============================================================================
; Send byte and autoincrement index
;
; Timing:
;   152 mcyc including CALL
;
0573:   CALL    04D9H       ;145    send SIO byte at 19200 baud
0575:   MOV     A,R0        ;1
0576:   INC     A           ;1
0577:   MOV     R0,A        ;1
0578:   RET                 ;2

;===============================================================================
; Send ModemLink (2800H bytes -> $0C00-33FF on computer)
;
0579:   CALL    04C8H       ;send ACK+Complete
057B:   MOV     R2,#00H     ;starting XROM address = 0000H
057D:   MOV     R0,#00H     ; "
057F:   MOV     R7,#11H     ;ending XROM address = 1100H
0581:   MOV     R3,#00H     ; "
0583:   CALL    05A7H       ;send from XROM for $0C00-1CFF
0585:   CLR     F1
0586:   CPL     F1
0587:   JMP     0597H       ;send T: handler and second half of ModemLink

;===============================================================================
; Send ModemLink part 2
;
0589:   MOV     R2,#13H     ;starting XROM address = 13C0H
058B:   MOV     R0,#0C0H    ; "
058D:   MOV     R7,#1FH     ;ending XROM address = 1F90H
058F:   MOV     R3,#90H     ; "
0591:   CALL    05A7H       ;send from XROM for $2830-33FF
0593:   MOV     A,R5        ;get checksum byte
0594:   CALL    04D9H       ;send SIO byte at 19200 baud
0596:   RET

;===============================================================================
; Send T: handler + ModemLink part 2
;
; Entry:
;   F1 = 0: only send T: handler
;   F1 = 1: send T: handler and ModemLink part 2
;
0597:   CALL    0700H       ;send from internal ROM for $1D00-256F
0599:   SEL     MB0
059A:   MOV     R2,#11H     ;starting XROM address = 1100H
059C:   MOV     R0,#00H     ; "
059E:   MOV     R7,#13H     ;ending XROM address = 13C0H
05A0:   MOV     R3,#0C0H    ; "
05A2:   CALL    05A7H       ;send from XROM for $2570-282F
05A4:   JF1     0589H       ;send ModemLink part 2 if requested
05A6:   RET

;===============================================================================
; Send from external ROM
;
; Entry:
;   R2:R0 = starting external ROM address
;   R7:R3 = ending external ROM address
;
; Timing:
;   155 mcyc/byte on non-last page
;   159 mcyc/byte on last page
;
05A7:   MOV     A,R2        ;get current page
05A8:   MOV     R1,#31H     ;select P2 shadow
05AA:   ORL     A,@R1       ;merge with P2 shadow bits 5:7
05AB:   OUTL    P2,A        ;update ROM A8-A12
05AC:   MOV     A,R2        ;1      get page address
05AD:   XRL     A,R7        ;1      check if ending page
05AE:   JNZ     05B4H       ;2      jump if not
05B0:   MOV     A,R0        ;1      get byte address
05B1:   XRL     A,R3        ;1      check if ending byte
05B2:   JZ      05BEH       ;2      exit if done
05B4:   MOVX    A,@R0       ;2      read byte from external ROM
05B5:   CALL    04D9H       ;145    send SIO byte at 19200 baud
05B7:   INC     R0          ;1      increment byte
05B8:   MOV     A,R0        ;1      check offset
05B9:   JNZ     05ACH       ;2      loop until page done
05BB:   INC     R2          ;increment page
05BC:   JMP     05A7H       ;loop for next page
05BE:   RET

;===============================================================================
05BF:   NOP
05C0:   NOP
05C1:   NOP
05C2:   NOP
05C3:   NOP
05C4:   NOP
05C5:   NOP
05C6:   NOP
05C7:   NOP
05C8:   NOP
05C9:   NOP
05CA:   NOP
05CB:   NOP
05CC:   NOP
05CD:   NOP
05CE:   NOP
05CF:   NOP
05D0:   NOP
05D1:   NOP
05D2:   NOP
05D3:   NOP
05D4:   NOP
05D5:   NOP
05D6:   NOP
05D7:   NOP
05D8:   NOP
05D9:   NOP
05DA:   NOP
05DB:   NOP
05DC:   NOP
05DD:   NOP
05DE:   NOP
05DF:   NOP
05E0:   NOP
05E1:   NOP
05E2:   NOP
05E3:   NOP
05E4:   NOP
05E5:   NOP
05E6:   NOP
05E7:   NOP
05E8:   NOP
05E9:   NOP
05EA:   NOP
05EB:   NOP
05EC:   NOP
05ED:   NOP
05EE:   NOP
05EF:   NOP
05F0:   NOP
05F1:   NOP
05F2:   NOP
05F3:   NOP
05F4:   NOP
05F5:   NOP
05F6:   NOP
05F7:   NOP
05F8:   NOP
05F9:   NOP
05FA:   NOP
05FB:   NOP
05FC:   NOP
05FD:   NOP
05FE:   NOP
05FF:   NOP

;===============================================================================
; Send fake disk boot sector
;
0600:   CALL    04C8H       ;send ACK+Complete
0602:   MOV     R0,#80H
0604:   MOV     A,R0
0605:   MOVP    A,@A        ;read byte from program store
0606:   CALL    0573H       ;send byte and autoincrement
0608:   JNZ     0604H
060A:   MOV     A,R5
060B:   CALL    04D9H       ;send SIO byte at 19200 baud
060D:   RET

;===============================================================================
060E:   NOP
060F:   NOP
0610:   NOP
0611:   NOP
0612:   NOP
0613:   NOP
0614:   NOP
0615:   NOP
0616:   NOP
0617:   NOP
0618:   NOP
0619:   NOP
061A:   NOP
061B:   NOP
061C:   NOP
061D:   NOP
061E:   NOP
061F:   NOP
0620:   NOP
0621:   NOP
0622:   NOP
0623:   NOP
0624:   NOP
0625:   NOP
0626:   NOP
0627:   NOP
0628:   NOP
0629:   NOP
062A:   NOP
062B:   NOP
062C:   NOP
062D:   NOP
062E:   NOP
062F:   NOP
0630:   NOP
0631:   NOP
0632:   NOP
0633:   NOP
0634:   NOP
0635:   NOP
0636:   NOP
0637:   NOP
0638:   NOP
0639:   NOP
063A:   NOP
063B:   NOP
063C:   NOP
063D:   NOP
063E:   NOP
063F:   NOP
0640:   NOP
0641:   NOP
0642:   NOP
0643:   NOP
0644:   NOP
0645:   NOP
0646:   NOP
0647:   NOP
0648:   NOP
0649:   NOP
064A:   NOP
064B:   NOP
064C:   NOP
064D:   NOP
064E:   NOP
064F:   NOP
0650:   NOP
0651:   NOP
0652:   NOP
0653:   NOP
0654:   NOP
0655:   NOP
0656:   NOP
0657:   NOP
0658:   NOP
0659:   NOP
065A:   NOP
065B:   NOP
065C:   NOP
065D:   NOP
065E:   NOP
065F:   NOP
0660:   NOP
0661:   NOP
0662:   NOP
0663:   NOP
0664:   NOP
0665:   NOP
0666:   NOP
0667:   NOP
0668:   NOP
0669:   NOP
066A:   NOP
066B:   NOP
066C:   NOP
066D:   NOP
066E:   NOP
066F:   NOP
0670:   NOP
0671:   NOP
0672:   NOP
0673:   NOP
0674:   NOP
0675:   NOP
0676:   NOP
0677:   NOP
0678:   NOP
0679:   NOP
067A:   NOP
067B:   NOP
067C:   NOP
067D:   NOP
067E:   NOP
067F:   NOP

;===============================================================================
; Fake boot sector
;
0680:   DB      000H,001H,000H,006H,0C0H,0E4H,0A9H,054H,0A2H,000H,0DDH,01AH,003H,018H,0F0H,024H
0690:   DB      0E8H,0E8H,0E8H,0E0H,036H,090H,0F3H,0A2H,009H,0BDH,035H,006H,09DH,000H,003H,0CAH
06A0:   DB      010H,0F7H,020H,059H,0E4H,038H,030H,00CH,020H,00CH,01DH,0A9H,000H,085H,00AH,0A9H
06B0:   DB      00CH,085H,00BH,018H,060H,058H,001H,03BH,040H,000H,00CH,006H,000H,000H,028H,000H
06C0:   DB      000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
06D0:   DB      000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
06E0:   DB      000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
06F0:   DB      000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H

;Boot sector disassembly
;
;0600: 00
;0601: 01
;0602: 00 06
;0604; C0 E4
;0606: A9 54        LDA #$54
;0608: A2 00        LDX #$00
;060A: DD 1A 03     CMP HATABS,X
;060D: 18           CLC
;060E: F0 24        BEQ $0634
;0610: E8           INX
;0611: E8           INX
;0612: E8           INX
;0613: E0 36        CPX #$36
;0615: 90 F3        BCC $060A
;0617: A2 09        LDX #$09
;0619: BD 35 06     LDA $0635,X
;061C: 9D 00 03     STA DDEVIC,X
;061F: CA           DEX
;0620: 10 F7        BPL $0619
;0622: 20 59 E4     JSR SIOV
;0625: 38           SEC
;0626: 30 0C        BMI $0634
;0628: 20 0C 1D     JSR $1D0C
;062B: A9 00        LDA #$00
;062D: 85 0A        STA DOSVEC
;062F: A9 0C        LDA #$0C
;0631: 85 0B        STA DOSVEC+1
;0633: 18           CLC
;0634: 60           RTS
;
;0635: 58           DDEVIC
;0636: 01           DUNIT
;0637: 3B           DCOMND
;0638: 40           DSTATS
;0639: 00
;063A: 0C           DTIMOT
;063B: 06           DBUFLO
;063C: 00           DBUFHI
;063D: 00           DBYTLO
;063E: 28           DBYTHI

;===============================================================================
; Send T: handler ($1D00-1DEF) + chain to next page
;
; Timing:
;   157 mcyc/byte
;
0700:   MOV     R0,#10H
0702:   MOV     A,R0        ;1
0703:   MOVP    A,@A        ;2
0704:   CALL    0573H       ;152    send byte and autoincrement
0706:   JNZ     0702H       ;2
0708:   SEL     MB1
0709:   JMP     0800H

;===============================================================================
070B:   NOP
070C:   NOP
070D:   NOP
070E:   NOP
070F:   NOP

;===============================================================================
0710:   DB      0A4H,01DH,0E5H,01DH,00CH,01FH,003H,01EH,09BH,01FH,0ABH,01FH,04CH,00AH,026H,000H
0720:   DB      020H,000H,000H,020H,04BH,023H,0A0H,0FFH,08CH,042H,004H,08CH,052H,004H,08CH,04FH
0730:   DB      004H,0ADH,050H,004H,048H,0C8H,08CH,050H,004H,020H,089H,022H,068H,08DH,050H,004H
0740:   DB      0A5H,008H,0F0H,00DH,0A9H,010H,08DH,042H,004H,0A2H,004H,08EH,04FH,004H,020H,0B9H
0750:   DB      022H,0A9H,000H,0A8H,099H,000H,004H,0C8H,010H,0FAH,0A9H,051H,08DH,042H,004H,08DH
0760:   DB      052H,004H,08DH,04FH,004H,020H,089H,022H,020H,0F1H,023H,0A2H,000H,08EH,042H,004H
0770:   DB      0BDH,01AH,003H,0F0H,00DH,0C9H,054H,0F0H,009H,0E8H,0E8H,0E8H,0E0H,020H,090H,0F0H
0780:   DB      0B0H,00FH,0A9H,054H,09DH,01AH,003H,0A9H,000H,09DH,01BH,003H,0A9H,01DH,09DH,01CH
0790:   DB      003H,0AEH,0A3H,01DH,0ACH,0A4H,01DH,0ECH,0E7H,002H,098H,0EDH,0E8H,002H,090H,00AH
07A0:   DB      08EH,0E7H,002H,086H,00EH,08CH,0E8H,002H,084H,00FH,0A9H,000H,08DH,05CH,004H,018H
07B0:   DB      060H,003H,00CH,00AH,027H,020H,008H,023H,0ADH,042H,004H,010H,003H,0A0H,096H,060H
07C0:   DB      0A5H,02AH,0A8H,029H,00CH,0D0H,003H,04CH,046H,01EH,098H,009H,090H,029H,0FEH,08DH
07D0:   DB      042H,004H,0A9H,000H,085H,007H,020H,04BH,023H,020H,067H,024H,0A9H,059H,08DH,052H
07E0:   DB      004H,0A2H,002H,020H,08BH,022H,090H,029H,020H,0F1H,023H,0A0H,000H,08CH,042H,004H
07F0:   DB      088H,084H,020H,0A0H,08BH,060H,020H,008H,023H,0ADH,042H,004H,0F0H,013H,020H,04FH

;===============================================================================
; Send T: handler ($1DF0-1EDF) + chain to next page
;
; Timing:
;   159S mcyc/byte
;
0800:   MOV     R0,#10H
0802:   MOV     A,R0        ;1
0803:   MOVP    A,@A        ;2
0804:   SEL     MB0         ;1
0805:   CALL    0573H       ;152    send byte and autoincrement
0807:   SEL     MB1         ;1
0808:   JNZ     0802H       ;2
080A:   JMP     0900H

;===============================================================================
080C:   NOP
080D:   NOP
080E:   NOP
080F:   NOP

;===============================================================================
0810:   DB      024H,0A9H,051H,08DH,052H,004H,020H,089H,022H,020H,0F1H,023H,0A9H,000H,08DH,042H
0820:   DB      004H,0A0H,001H,060H,020H,008H,023H,08DH,052H,004H,0AEH,051H,004H,0D0H,016H,0A6H
0830:   DB      007H,0F0H,059H,0C9H,01BH,0F0H,006H,0C9H,09BH,0D0H,026H,0F0H,005H,0A9H,080H,08DH
0840:   DB      051H,004H,0A0H,001H,060H,010H,040H,0C9H,01BH,0F0H,0F7H,0ADH,042H,004H,04AH,0ADH
0850:   DB      052H,004H,090H,004H,0C9H,059H,0D0H,009H,038H,0E9H,041H,090H,004H,0C9H,01AH,090H
0860:   DB      010H,0A9H,000H,08DH,051H,004H,0ADH,045H,004H,009H,001H,08DH,045H,004H,0A0H,084H
0870:   DB      060H,0AAH,0BDH,06EH,020H,018H,069H,088H,08DH,04AH,004H,0A9H,020H,069H,000H,08DH
0880:   DB      04BH,004H,0A9H,000H,08DH,051H,004H,0A0H,001H,06CH,04AH,004H,0ADH,042H,004H,029H
0890:   DB      008H,0D0H,003H,0A0H,087H,060H,0ADH,042H,004H,04AH,0B0H,0CAH,0ADH,043H,004H,029H
08A0:   DB      030H,0A8H,0F0H,004H,0C9H,020H,0B0H,034H,0ADH,052H,004H,0C9H,09BH,0D0H,017H,0ADH
08B0:   DB      043H,004H,029H,040H,0F0H,00CH,0A9H,00DH,020H,0B9H,01EH,010H,001H,060H,0A9H,00AH
08C0:   DB      0D0H,017H,0A9H,00DH,0D0H,013H,0C0H,010H,0F0H,004H,029H,07FH,010H,00BH,0C9H,020H
08D0:   DB      090H,004H,0C9H,07DH,090H,003H,0A0H,001H,060H,08DH,052H,004H,0ADH,043H,004H,029H
08E0:   DB      003H,0F0H,01EH,0C9H,003H,0F0H,012H,0A8H,020H,082H,024H,020H,077H,024H,098H,029H
08F0:   DB      002H,0F0H,004H,090H,00CH,010H,002H,0B0H,008H,0ADH,052H,004H,009H,080H,08DH,052H

;===============================================================================
; Send T: handler ($1EE0-1FCF) + chain to next page
;
0900:   MOV     R0,#10H
0902:   MOV     A,R0
0903:   MOVP    A,@A
0904:   SEL     MB0
0905:   CALL    0573H       ;send byte and autoincrement
0907:   SEL     MB1
0908:   JNZ     0902H
090A:   JMP     0A00H

;===============================================================================
090C:   NOP
090D:   NOP
090E:   NOP
090F:   NOP

;===============================================================================
0910:   DB      004H,020H,02BH,023H,020H,019H,023H,0ADH,001H,004H,0C9H,03FH,0B0H,0F3H,078H,0ACH
0920:   DB      049H,004H,0ADH,052H,004H,099H,002H,004H,020H,08BH,024H,08DH,049H,004H,0EEH,001H
0930:   DB      004H,0ADH,050H,004H,0D0H,003H,020H,05DH,024H,058H,0A0H,001H,060H,020H,008H,023H
0940:   DB      0ADH,042H,004H,029H,004H,0D0H,003H,0A0H,083H,060H,0ADH,042H,004H,04AH,090H,003H
0950:   DB      04CH,046H,01EH,058H,020H,02BH,023H,020H,019H,023H,078H,0ACH,047H,004H,0CCH,046H
0960:   DB      004H,0F0H,0F0H,0B9H,00AH,026H,08DH,052H,004H,020H,08BH,024H,08DH,047H,004H,0CEH
0970:   DB      000H,004H,058H,0ADH,043H,004H,04AH,04AH,029H,003H,0F0H,023H,0C9H,003H,0F0H,01CH
0980:   DB      0A8H,0ADH,052H,004H,020H,077H,024H,098H,029H,002H,0F0H,004H,090H,00EH,010H,002H
0990:   DB      0B0H,00AH,0A6H,021H,0A9H,020H,00DH,045H,004H,08DH,045H,004H,020H,082H,024H,0ADH
09A0:   DB      043H,004H,029H,030H,0C9H,020H,090H,006H,0ADH,052H,004H,0A0H,001H,060H,0A8H,020H
09B0:   DB      082H,024H,0C9H,00DH,0D0H,004H,0A9H,09BH,0D0H,00FH,0C0H,000H,0F0H,00BH,0C9H,020H
09C0:   DB      090H,004H,0C9H,07DH,090H,003H,0ADH,04CH,004H,0A0H,001H,060H,0ADH,042H,004H,04AH
09D0:   DB      029H,040H,0F0H,005H,0B0H,003H,04CH,0ECH,020H,04CH,046H,01EH,0A0H,092H,060H,02CH
09E0:   DB      00EH,0D2H,010H,003H,04CH,000H,000H,048H,0A9H,07FH,08DH,00EH,0D2H,0A5H,010H,08DH
09F0:   DB      00EH,0D2H,0A9H,000H,08DH,04FH,004H,068H,040H,0D8H,098H,048H,0ACH,046H,004H,0ADH


;===============================================================================
; Send T: handler ($1FD0-20BF) + chain to next page
;
0A00:   MOV     R0,#10H
0A02:   MOV     A,R0
0A03:   MOVP    A,@A
0A04:   SEL     MB0
0A05:   CALL    0573H       ;send byte and autoincrement
0A07:   SEL     MB1
0A08:   JNZ     0A02H
0A0A:   JMP     0B00H

;===============================================================================
0A0C:   NOP
0A0D:   NOP
0A0E:   NOP
0A0F:   NOP

;===============================================================================
0A10:   DB      000H,004H,0F0H,00FH,0C9H,040H,0D0H,00BH,0ADH,045H,004H,009H,010H,08DH,045H,004H
0A20:   DB      0CEH,000H,004H,0ADH,00DH,0D2H,099H,00AH,026H,020H,08BH,024H,08DH,046H,004H,0ACH
0A30:   DB      000H,004H,020H,08BH,024H,08DH,000H,004H,0ADH,00FH,0D2H,08DH,00AH,0D2H,049H,0FFH
0A40:   DB      029H,0C0H,00DH,045H,004H,08DH,045H,004H,068H,0A8H,068H,040H,0D8H,098H,048H,0ADH
0A50:   DB      001H,004H,0D0H,00CH,0A9H,0E7H,025H,010H,085H,010H,08DH,00EH,0D2H,04CH,008H,020H
0A60:   DB      0ACH,048H,004H,0B9H,002H,004H,08DH,00DH,0D2H,020H,08BH,024H,08DH,048H,004H,0CEH
0A70:   DB      001H,004H,0ADH,00EH,0D2H,029H,008H,0F0H,0F9H,0D0H,0CDH,0D8H,098H,048H,0ADH,050H
0A80:   DB      004H,0F0H,007H,0A9H,000H,08DH,050H,004H,0F0H,0BEH,0ADH,044H,004H,029H,03EH,08DH
0A90:   DB      044H,004H,04CH,008H,020H,0D8H,098H,048H,0ADH,044H,004H,049H,080H,08DH,044H,004H
0AA0:   DB      029H,080H,0F0H,0E6H,0ADH,044H,004H,029H,0BFH,08DH,044H,004H,0D0H,09AH,00CH,000H
0AB0:   DB      045H,000H,05FH,064H,000H,0E0H,087H,095H,006H,0B4H,0C0H,0CDH,0D5H,0DCH,000H,000H
0AC0:   DB      000H,000H,000H,000H,09FH,0A9H,0FFH,003H,04CH,041H,01EH,04CH,0CFH,021H,04CH,04BH
0AD0:   DB      022H,04CH,0ECH,021H,04CH,0A4H,020H,04CH,0BAH,020H,08DH,04CH,004H,0A0H,000H,08CH
0AE0:   DB      051H,004H,0C8H,060H,0A9H,002H,08DH,051H,004H,018H,0ADH,04AH,004H,069H,003H,08DH
0AF0:   DB      04AH,004H,090H,003H,0EEH,04BH,004H,0A0H,001H,060H,029H,070H,08DH,052H,004H,0ADH


;===============================================================================
; Send T: handler ($20C0-21AF) + chain to next page
;
0B00:   MOV     R0,#10H
0B02:   MOV     A,R0
0B03:   MOVP    A,@A
0B04:   SEL     MB0
0B05:   CALL    0573H       ;send byte and autoincrement
0B07:   SEL     MB1
0B08:   JNZ     0B02H
0B0A:   JMP     0C00H

;===============================================================================
0B0C:   NOP
0B0D:   NOP
0B0E:   NOP
0B0F:   NOP

;===============================================================================
0B10:   DB      043H,004H,029H,08FH,00DH,052H,004H,08DH,043H,004H,04CH,0A9H,020H,04CH,0E3H,020H
0B20:   DB      029H,00FH,08DH,052H,004H,0ADH,043H,004H,029H,0F0H,00DH,052H,004H,08DH,043H,004H
0B30:   DB      04CH,09DH,020H,0A9H,001H,0D0H,0BFH,0A9H,000H,085H,007H,060H,0ADH,001H,004H,08DH
0B40:   DB      0EDH,002H,0ADH,000H,004H,08DH,0ECH,002H,0ADH,044H,004H,029H,0B5H,08DH,0EBH,002H
0B50:   DB      0ADH,045H,004H,029H,0F1H,08DH,0EAH,002H,0A0H,000H,08CH,045H,004H,0C8H,060H,020H
0B60:   DB      089H,022H,0ADH,044H,004H,029H,0EFH,08DH,044H,004H,0A0H,001H,060H,020H,089H,022H
0B70:   DB      0ADH,044H,004H,009H,010H,0D0H,0F0H,020H,089H,022H,0ADH,044H,004H,009H,020H,0D0H
0B80:   DB      0E6H,020H,089H,022H,0ADH,044H,004H,029H,0DFH,04CH,017H,021H,0A2H,004H,020H,08BH
0B90:   DB      022H,0ADH,044H,004H,009H,001H,0D0H,0CFH,0A2H,004H,020H,08BH,022H,0ADH,044H,004H
0BA0:   DB      029H,03EH,04CH,017H,021H,0ADH,044H,004H,029H,0FBH,04CH,017H,021H,0ADH,044H,004H
0BB0:   DB      009H,004H,0D0H,0B3H,020H,089H,022H,060H,0ADH,044H,004H,00AH,0B0H,003H,04CH,01FH
0BC0:   DB      023H,0ADH,042H,004H,009H,010H,08DH,042H,004H,020H,089H,022H,090H,003H,04CH,0ECH
0BD0:   DB      022H,0EEH,050H,004H,0A0H,001H,060H,0ADH,042H,004H,0A8H,029H,001H,0D0H,003H,0A0H
0BE0:   DB      001H,060H,098H,029H,0FEH,009H,010H,08DH,042H,004H,078H,020H,0A3H,023H,0A5H,010H
0BF0:   DB      009H,020H,08DH,00EH,0D2H,085H,010H,058H,020H,067H,024H,0A2H,002H,020H,08BH,022H


;===============================================================================
; Send T: handler ($21B0-229F) + chain to next page
;
0C00:   MOV     R0,#10H
0C02:   MOV     A,R0
0C03:   MOVP    A,@A
0C04:   SEL     MB0
0C05:   CALL    0573H       ;send byte and autoincrement
0C07:   SEL     MB1
0C08:   JNZ     0C02H
0C0A:   JMP     0D00H

;===============================================================================
0C0C:   NOP
0C0D:   NOP
0C0E:   NOP
0C0F:   NOP

;===============================================================================
0C10:   DB      090H,0DDH,0ADH,042H,004H,009H,010H,08DH,042H,004H,0A2H,002H,020H,08BH,022H,090H
0C20:   DB      0CEH,020H,0F1H,023H,0ADH,042H,004H,009H,001H,08DH,042H,004H,0A0H,08BH,060H,0ADH
0C30:   DB      042H,004H,009H,010H,08DH,042H,004H,0A2H,002H,020H,08BH,022H,0B0H,0F9H,0ADH,042H
0C40:   DB      004H,009H,001H,08DH,042H,004H,020H,0F1H,023H,0A0H,001H,060H,029H,00FH,0C9H,00BH
0C50:   DB      0D0H,007H,0A0H,000H,08CH,051H,004H,0F0H,00EH,0C9H,00CH,0D0H,00AH,0A0H,0B4H,0A2H
0C60:   DB      000H,020H,06BH,024H,0A0H,001H,060H,08DH,052H,004H,08DH,053H,004H,0A8H,0ADH,044H
0C70:   DB      004H,029H,004H,0F0H,021H,0C0H,00BH,0D0H,017H,020H,07BH,023H,020H,067H,024H,0A9H
0C80:   DB      050H,08DH,052H,004H,020H,089H,022H,0ADH,053H,004H,08DH,052H,004H,04CH,004H,022H
0C90:   DB      020H,094H,024H,04CH,004H,022H,0ADH,052H,004H,0D0H,005H,0A9H,00AH,08DH,052H,004H
0CA0:   DB      0C9H,00CH,0B0H,0E9H,0A2H,004H,020H,08BH,022H,090H,0E2H,0ADH,044H,004H,00AH,090H
0CB0:   DB      003H,04CH,041H,01EH,0A9H,001H,08DH,051H,004H,0ADH,052H,004H,08DH,053H,004H,0ADH
0CC0:   DB      044H,004H,029H,004H,0F0H,00DH,0A9H,04FH,08DH,052H,004H,0A2H,004H,020H,08BH,022H
0CD0:   DB      04CH,078H,022H,0A2H,004H,020H,08BH,022H,0ADH,053H,004H,08DH,052H,004H,0ADH,044H
0CE0:   DB      004H,009H,001H,08DH,044H,004H,04CH,0A9H,020H,0A2H,000H,0ADH,050H,004H,0D0H,0FBH
0CF0:   DB      020H,04FH,024H,0ADH,00EH,0D2H,029H,008H,0D0H,0F9H,0A9H,035H,08DH,003H,0D3H,08DH


;===============================================================================
; Send T: handler ($22A0-238F) + chain to next page
;
0D00:   MOV     R0,#10H
0D02:   MOV     A,R0
0D03:   MOVP    A,@A
0D04:   SEL     MB0
0D05:   CALL    0573H       ;send byte and autoincrement
0D07:   SEL     MB1
0D08:   JNZ     0D02H
0D0A:   JMP     0E00H

;===============================================================================
0D0C:   NOP
0D0D:   NOP
0D0E:   NOP
0D0F:   NOP

;===============================================================================
0D10:   DB      050H,004H,078H,0ACH,049H,004H,0ADH,052H,004H,099H,002H,004H,020H,08BH,024H,08DH
0D20:   DB      049H,004H,0EEH,001H,004H,058H,020H,04FH,024H,0BCH,002H,023H,0BDH,003H,023H,0AAH
0D30:   DB      020H,032H,024H,020H,02BH,023H,0ADH,050H,004H,0F0H,028H,0ADH,04EH,004H,0D0H,0F3H
0D40:   DB      08DH,051H,004H,08DH,050H,004H,0A9H,03DH,08DH,003H,0D3H,0ADH,042H,004H,029H,010H
0D50:   DB      0F0H,00AH,0ADH,042H,004H,029H,0EFH,08DH,042H,004H,038H,060H,0AEH,04DH,004H,09AH
0D60:   DB      0A0H,08BH,060H,0A9H,03DH,08DH,003H,0D3H,0ADH,042H,004H,029H,0EFH,08DH,042H,004H
0D70:   DB      018H,060H,008H,000H,03CH,000H,0B4H,000H,0A8H,0ADH,045H,004H,029H,0FEH,08DH,045H
0D80:   DB      004H,098H,0BAH,0E8H,0E8H,08EH,04DH,004H,060H,02CH,044H,004H,010H,001H,060H,0AEH
0D90:   DB      04DH,004H,09AH,0A9H,000H,08DH,051H,004H,0A0H,088H,060H,0ADH,04FH,004H,0F0H,001H
0DA0:   DB      060H,0AEH,04DH,004H,09AH,0EEH,04FH,004H,08DH,051H,004H,0ADH,042H,004H,029H,0EFH
0DB0:   DB      08DH,042H,004H,0A9H,03DH,08DH,003H,0D3H,0A0H,080H,060H,078H,020H,0A3H,023H,0A9H
0DC0:   DB      000H,08DH,000H,004H,08DH,001H,004H,0A0H,005H,099H,044H,004H,088H,010H,0FAH,085H
0DD0:   DB      007H,08DH,051H,004H,0A9H,0C7H,025H,010H,009H,020H,08DH,00EH,0D2H,085H,010H,058H
0DE0:   DB      060H,0C9H,01FH,00CH,020H,00CH,020H,03BH,020H,055H,020H,0A9H,007H,02DH,032H,002H
0DF0:   DB      009H,070H,08DH,032H,002H,08DH,00FH,0D2H,08DH,00AH,0D2H,0A9H,078H,08DH,008H,0D2H


;===============================================================================
; Send T: handler ($2390-247F) + chain to next page
;
0E00:   MOV     R0,#10H
0E02:   MOV     A,R0
0E03:   MOVP    A,@A
0E04:   SEL     MB0
0E05:   CALL    0D73H
0E07:   SEL     MB1
0E08:   JNZ     0E02H
0E0A:   JMP     0F00H

;===============================================================================
0E0C:   NOP
0E0D:   NOP
0E0E:   NOP
0E0F:   NOP

;===============================================================================
0E10:   DB      0A2H,007H,0A9H,0A0H,09DH,000H,0D2H,0CAH,010H,0FAH,0A9H,00BH,08DH,002H,0D2H,08DH
0E20:   DB      006H,0D2H,060H,020H,07BH,023H,0A2H,005H,0BDH,00AH,002H,09DH,0E7H,023H,0BDH,071H
0E30:   DB      023H,09DH,00AH,002H,0CAH,010H,0F1H,0A2H,003H,0BDH,002H,002H,09DH,0EDH,023H,0BDH
0E40:   DB      077H,023H,09DH,002H,002H,0CAH,010H,0F1H,0ADH,002H,0D3H,009H,001H,08DH,002H,0D3H
0E50:   DB      0ADH,016H,002H,08DH,0B5H,01FH,0A9H,0AFH,08DH,016H,002H,0ADH,017H,002H,08DH,0B6H
0E60:   DB      01FH,0A9H,01FH,08DH,017H,002H,060H,000H,000H,000H,000H,000H,000H,000H,000H,000H
0E70:   DB      000H,078H,0ADH,0B5H,01FH,08DH,016H,002H,0ADH,0B6H,01FH,08DH,017H,002H,0A0H,005H
0E80:   DB      0B9H,0E7H,023H,099H,00AH,002H,088H,010H,0F7H,0A0H,003H,0B9H,0EDH,023H,099H,002H
0E90:   DB      002H,088H,010H,0F7H,0ADH,002H,0D3H,029H,0FEH,08DH,002H,0D3H,0A9H,0C7H,025H,010H
0EA0:   DB      085H,010H,08DH,00EH,0D2H,0A2H,006H,0A9H,000H,09DH,001H,0D2H,0CAH,0CAH,010H,0F9H
0EB0:   DB      058H,060H,0A9H,049H,08DH,026H,002H,0A9H,024H,08DH,027H,002H,0A9H,001H,078H,020H
0EC0:   DB      05CH,0E4H,0A9H,001H,08DH,04EH,004H,058H,060H,0A9H,000H,08DH,04EH,004H,060H,078H
0ED0:   DB      020H,05DH,024H,058H,020H,02BH,023H,0ADH,001H,004H,0D0H,0F8H,060H,0A5H,010H,009H
0EE0:   DB      018H,085H,010H,08DH,00EH,0D2H,060H,0A2H,000H,0A0H,003H,020H,032H,024H,020H,02BH
0EF0:   DB      023H,0ADH,04EH,004H,0D0H,0F8H,060H,0A2H,000H,04AH,090H,001H,0E8H,0D0H,0FAH,08AH


;===============================================================================
; Send T: handler ($2480-256F) + chain to next page
;
0F00:   MOV     R0,#10H
0F02:   MOV     A,R0
0F03:   MOVP    A,@A
0F04:   SEL     MB0
0F05:   CALL    0573H       ;send byte and autoincrement
0F07:   SEL     MB1
0F08:   JNZ     0F02H
0F0A:   RET

;===============================================================================
0F0B:   NOP
0F0C:   NOP
0F0D:   NOP
0F0E:   NOP
0F0F:   NOP

;===============================================================================
0F10:   DB      04AH,060H,0ADH,052H,004H,029H,07FH,08DH,052H,004H,060H,0C8H,098H,0C9H,040H,090H
0F20:   DB      002H,0A9H,000H,060H,0A9H,000H,08DH,008H,0D2H,08DH,001H,0D2H,08DH,003H,0D2H,08DH
0F30:   DB      005H,0D2H,08DH,007H,0D2H,08DH,000H,004H,0A9H,000H,0A2H,003H,09DH,054H,004H,0CAH
0F40:   DB      010H,0FAH,0ACH,052H,004H,0B9H,0F3H,024H,0F0H,038H,029H,00FH,048H,029H,003H,00AH
0F50:   DB      0AAH,0BDH,00BH,025H,08DH,058H,004H,0BDH,00CH,025H,08DH,059H,004H,068H,04AH,029H
0F60:   DB      006H,0AAH,0BDH,003H,025H,08DH,05AH,004H,0BDH,004H,025H,08DH,05BH,004H,0A2H,000H
0F70:   DB      08EH,00EH,0D4H,008H,0D8H,078H,020H,011H,025H,020H,084H,025H,028H,0A9H,040H,08DH
0F80:   DB      00EH,0D4H,060H,00DH,080H,001H,002H,004H,005H,006H,008H,009H,00AH,00CH,000H,000H
0F90:   DB      000H,00EH,000H,0B4H,016H,014H,019H,0C0H,01BH,0A6H,01EH,061H,027H,083H,02BH,01BH
0FA0:   DB      030H,0A9H,000H,08DH,060H,004H,08DH,05EH,004H,0AEH,055H,004H,02CH,054H,004H,020H
0FB0:   DB      0ABH,025H,04AH,04AH,04AH,04AH,020H,0C1H,025H,08DH,05DH,004H,0AEH,057H,004H,02CH
0FC0:   DB      056H,004H,020H,0ABH,025H,029H,00FH,020H,0C1H,025H,018H,06DH,05DH,004H,06DH,05CH
0FD0:   DB      004H,029H,03CH,0AEH,05EH,004H,030H,007H,00AH,00AH,08DH,05FH,004H,090H,00BH,04AH
0FE0:   DB      04AH,00DH,05FH,004H,0AEH,060H,004H,09DH,00AH,026H,0D8H,0A2H,002H,0BDH,054H,004H
0FF0:   DB      018H,07DH,058H,004H,09DH,054H,004H,0BDH,055H,004H,07DH,059H,004H,09DH,055H,004H
